/*
 * Filename:    AnalyticFormula.java
 * Copyright:   2014 中国平安保险（集团）股份有限公司 版权所有
 * Company:     平安科技养老险及健康险系统开发部
 * Create at:   2014年10月10日
 */
package com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.calculation;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.util.ContentFinalUtil;
import com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.vo.CalculationFormulaVo;
import com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.vo.FormulaItemVo;
import com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.vo.FormulaLumpVo;
import com.paic.mhis.hcpms.quota.calculationreport.calculationkpi.common.vo.ItemPropertiesVo;

public class AnalyticFormula {
	private CalculationFormulaVo calculationFormulaVo;

	public CalculationFormulaVo getCalculationFormulaVo() {
		return calculationFormulaVo;
	}

	public void setCalculationFormulaVo(CalculationFormulaVo calculationFormulaVo) {
		this.calculationFormulaVo = calculationFormulaVo;
	}

	public void createFormual() {
		List<FormulaLumpVo> lumpVos = new ArrayList<FormulaLumpVo>();
		int lumpLevl = 0;
		String formulExpression = calculationFormulaVo.getFormula();
		while (formulExpression.indexOf(ContentFinalUtil.PAREMTH_LEFT) != -1) {
			String formulaLump = createformulaLump(formulExpression);
			lumpVos.add(lumpLevl, createFormulaLump(formulaLump, ++lumpLevl));
			formulExpression = formulExpression.replace(ContentFinalUtil.PAREMTH_LEFT + formulaLump
					+ ContentFinalUtil.PAREMTH_RIGHT, ContentFinalUtil.PARM_LUMP + lumpLevl);
		}
		lumpVos.add(lumpLevl, createFormulaLump(formulExpression, ++lumpLevl));
		calculationFormulaVo.setLumpList(lumpVos);
	}

	public FormulaLumpVo createFormulaLump(String formulExpression, int lumpLevl) {
		FormulaLumpVo lumpVo = new FormulaLumpVo();
		lumpVo.setLumpId(lumpLevl);
		lumpVo.setLumpName(ContentFinalUtil.PARM_LUMP + lumpLevl);
		lumpVo.setLumpFormual(formulExpression);
		lumpVo.setItemList(analyticFormulaItem(formulExpression));
		return lumpVo;
	}

	public String createformulaLump(String formulExpression) {
		String returnStr = "";
		int right = formulExpression.indexOf(ContentFinalUtil.PAREMTH_RIGHT);
		int left = formulExpression.indexOf(ContentFinalUtil.PAREMTH_LEFT);
		int nextIndex = left + 1;
		int leftNext = formulExpression.indexOf(ContentFinalUtil.PAREMTH_LEFT, nextIndex);
		while (leftNext != -1 && leftNext < right) {
			left = leftNext;
			nextIndex = left + 1;
			leftNext = formulExpression.indexOf(ContentFinalUtil.PAREMTH_LEFT, nextIndex);
		}
		returnStr = formulExpression.substring(nextIndex, right);
		return returnStr;
	}

	public List<FormulaItemVo> analyticFormulaItem(String formulExpression) {
		List<FormulaItemVo> itemVos = new ArrayList<FormulaItemVo>();
		String[] propertis = {};
		String[] formulaType = {};
		String test = "";
		int itemVosSize = 0;
		for (int i = 0; i < formulExpression.length(); i++) {
			switch (formulExpression.charAt(i)) {
			case '+':
			case '-':
			case '*':
			case '/':
				if (!"".equals(test) && test != null) {
					propertis = addArrayLength(propertis, 1);
					formulaType = addArrayLength(formulaType, 1);
					formulaType[formulaType.length - 1] = formulExpression.charAt(i) + "";
					propertis[propertis.length - 1] = test;
					test = "";
					++itemVosSize;
				} else {
					test += formulExpression.charAt(i);
				}
				break;
			default:
				test += formulExpression.charAt(i);
				break;
			}
		}
		propertis = addArrayLength(propertis, 1);
		propertis[propertis.length - 1] = test;
		if (itemVosSize > 0) {
			for (int i = 0; i < itemVosSize; i++) {
				FormulaItemVo vo = new FormulaItemVo();
				vo.setItemId(i + 1);
				vo.setItemName(ContentFinalUtil.PARM_SINGLE + (i + 1));
				int index = calculationLevl(formulaType);
				vo.setFormulaType(formulaType[index]);
				vo.setFormual(propertis[index] + formulaType[index] + propertis[index + 1]);
				setLeftProperties(propertis[index], vo);
				setRightProperties(propertis[index + 1], vo);
				// vo.setLeftProper(setItemProperties(propertis[index]));
				// vo.setRightProper(setItemProperties(propertis[index + 1]));
				vo.setOrder(i);
				formulaType = removeArrayValue(formulaType, index);
				propertis = mergeArrayTowChangeOne(propertis, index, index + 1, vo.getItemName());
				itemVos.add(i, vo);
			}
		} else {
			FormulaItemVo vo = new FormulaItemVo();
			vo.setItemId(1);
			vo.setItemName(ContentFinalUtil.PARM_SINGLE + 1);
			vo.setFormulaType(ContentFinalUtil.MATH_EQUAL);
			vo.setFormual(propertis[0]);
			vo.setProperLeftType(ContentFinalUtil.PRO_TYPE_P);
			vo.setProperLeftName(propertis[0]);
			vo.setOrder(0);
			itemVos.add(0, vo);
		}
		return itemVos;
	}

	public void setLeftProperties(String propertis, FormulaItemVo vo) {
		if (isNum(propertis)) {
			vo.setProperLeftType(ContentFinalUtil.PRO_TYPE_C);
			vo.setProperLeftName(ContentFinalUtil.PRO_TYPE_C + propertis);
			vo.setProperLeftValue(new BigDecimal(propertis));
		} else if (propertis.contains(ContentFinalUtil.PARM_LUMP)) {
			vo.setProperLeftType(ContentFinalUtil.PRO_TYPE_L);
			vo.setProperLeftName(propertis);
		} else if (propertis.contains(ContentFinalUtil.PARM_SINGLE)) {
			vo.setProperLeftType(ContentFinalUtil.PRO_TYPE_S);
			vo.setProperLeftName(propertis);
		} else {
			vo.setProperLeftType(ContentFinalUtil.PRO_TYPE_P);
			vo.setProperLeftName(propertis);
		}

	}

	public void setRightProperties(String propertis, FormulaItemVo vo) {
		if (isNum(propertis)) {
			vo.setProperRightType(ContentFinalUtil.PRO_TYPE_C);
			vo.setProperRightName(ContentFinalUtil.PRO_TYPE_C + propertis);
			vo.setProperRightValue(new BigDecimal(propertis));
		} else if (propertis.contains(ContentFinalUtil.PARM_LUMP)) {
			vo.setProperRightType(ContentFinalUtil.PRO_TYPE_L);
			vo.setProperRightName(propertis);
		} else if (propertis.contains(ContentFinalUtil.PARM_SINGLE)) {
			vo.setProperRightType(ContentFinalUtil.PRO_TYPE_S);
			vo.setProperRightName(propertis);
		} else {
			vo.setProperRightType(ContentFinalUtil.PRO_TYPE_P);
			vo.setProperRightName(propertis);
		}

	}

	public ItemPropertiesVo setItemProperties(String propertiesStr) {
		ItemPropertiesVo vo = new ItemPropertiesVo();
		if (isNum(propertiesStr)) {
			vo.setPropertiesType(ContentFinalUtil.PRO_TYPE_C);
			vo.setPropertiesName(ContentFinalUtil.PRO_TYPE_C + propertiesStr);
			vo.setBgValue(new BigDecimal(propertiesStr));
			vo.setLevel(0);
		} else if (propertiesStr.contains(ContentFinalUtil.PARM_LUMP)) {
			vo.setPropertiesType(ContentFinalUtil.PRO_TYPE_L);
			vo.setPropertiesName(propertiesStr);
			vo.setLevel(Integer.parseInt(propertiesStr.replaceAll("\\D+", "")));
		} else if (propertiesStr.contains(ContentFinalUtil.PARM_SINGLE)) {
			vo.setPropertiesType(ContentFinalUtil.PRO_TYPE_S);
			vo.setPropertiesName(propertiesStr);
			vo.setLevel(Integer.parseInt(propertiesStr.replaceAll("\\D+", "")));
		} else {
			vo.setPropertiesType(ContentFinalUtil.PRO_TYPE_P);
			vo.setPropertiesName(propertiesStr);
			vo.setLevel(1);
		}
		return vo;
	}

	public int calculationLevl(String[] formulaType) {
		int index = 0;
		if (formulaType.length > 1) {
			if (equelsTypeIsArray(formulaType, ContentFinalUtil.MATH_MUL)
					|| equelsTypeIsArray(formulaType, ContentFinalUtil.MATH_DIV)) {
				for (int i = 0; i < formulaType.length; i++) {
					if (ContentFinalUtil.MATH_MUL.equals(formulaType[i])
							|| ContentFinalUtil.MATH_DIV.equals(formulaType[i])) {
						index = i;
						break;
					}
				}
			} else {
				index = 0;
			}
		}
		return index;
	}

	public boolean equelsTypeIsArray(String[] formulaType, String type) {
		if (formulaType.length > 0)
			for (String str : formulaType) {
				if (type.equals(str)) {
					return true;
				}
			}
		return false;
	}

	public String[] mergeArrayTowChangeOne(String[] propertis, int index, int nextIndex, String itemName) {
		String[] str = new String[propertis.length - 1];
		int j = 0;
		for (int i = 0; i < propertis.length; i++) {
			if (i != index && i != nextIndex) {
				str[j] = propertis[i];
				++j;
			} else if (i == index) {
				str[j] = itemName;
				++j;
			}
		}
		return str;
	}

	public String[] removeArrayValue(String[] formulaType, int index) {
		String[] str = new String[formulaType.length - 1];
		int j = 0;
		for (int i = 0; i < formulaType.length; i++) {
			if (i != index) {
				str[j] = formulaType[i];
				++j;
			}
		}
		return str;
	}

	public String[] addArrayLength(String[] str, int length) {
		String[] array = new String[str.length + length];
		if (str.length > 0) {
			for (int i = 0; i < str.length; i++) {
				array[i] = str[i];
			}
		}
		return array;
	}

	public boolean isNum(String str) {
		return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
	}
}
